package post

import (
	"context"
	// "fmt"
	"strconv"
	"strings"

	"mall/common/globalkey"
	"mall/common/jwt"
	"mall/common/utils/pointy"
	"mall/service/blog/rpc/blogclient"
	"mall/service/forum/api/internal/svc"
	"mall/service/forum/api/internal/types"
	"mall/service/forum/rpc/forumclient"

	// "github.com/sirupsen/logrus"
	"github.com/zeromicro/go-zero/core/logx"
)

type GetReviewByIdLogic struct {
	logx.Logger
	ctx    context.Context
	svcCtx *svc.ServiceContext
}

func NewGetReviewByIdLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetReviewByIdLogic {
	return &GetReviewByIdLogic{
		Logger: logx.WithContext(ctx),
		ctx:    ctx,
		svcCtx: svcCtx,
	}
}

func (l *GetReviewByIdLogic) GetReviewById(
	req *types.ForumPostIdReq,
	headers *[]*types.Header,
) (*types.ReviewInfo, error) {
	if req.Id == nil || *req.Id == 0 {
		return &types.ReviewInfo{}, nil
	}

	userId := jwt.GetUserId(l.ctx)

	if req.AuthorId != nil && *req.AuthorId > 0 {
		return l.getReviewById(req.Id, userId, *req.AuthorId)
	}

	preload := "forumPost:Id,Title,AuthorId,AuthorName,AuthorAvatar,AuthorRankId,AuthorRoleId,ContentHtml,Excerpt,CommentStatus,PublicDate,PhotoCount"
	eagerLoad := "forumPost:forumMedia,forumPostMeta,forumCard,forumTerm,forumUser"
	preload += ";forumUser:Id,UserId,Nickname,Avatar,Signature"
	preload += ";forumMedia:Id,Uid,Uri,Url,Order,Thumbnail,altText,metaData"
	preload += ";forumPostMeta:mediaId,mediaUrl,viewCount,commentCount,forwardCount"
	preload += ";forumTerm:Id,Name,Slug"
	preload += ";forumCard:ObjectId,ObjectType,LinkUrl,PicUrl,Title,Subtitle,Label,Price"
	var filters []string
	filters = append(filters, "ForumId,equalTo:"+strconv.FormatInt(l.svcCtx.Config.Query.ColumnForumId, 10))
	filters = append(filters, "Status,equalTo:"+strconv.FormatInt(int64(globalkey.StatusApproved), 10))
	platformId := globalkey.ThirdPartyPlatformWechatMini

	var searchLogId *uint64
	if req.SearchId != nil && *req.SearchId > 0 {
		searchLogId = pointy.GetPointer(uint64(*req.SearchId))
	} else {
		searchLogId = pointy.GetPointer(uint64(0))
	}

	res, err := l.svcCtx.ForumRpc.GetReviewById(l.ctx, &forumclient.BaseIdReq{
		Id:          req.Id,
		Preload:     pointy.GetPointer(preload),
		EagerLoad:   pointy.GetPointer(eagerLoad),
		Filter:      pointy.GetPointer(strings.Join(filters, ";")),
		VisitorId:   pointy.GetPointer(userId),
		PlatformId:  pointy.GetPointer(platformId),
		SearchLogId: searchLogId,
	})
	if err != nil {
		logx.Errorw("GetReviewById GetPostById err", logx.Field("detail", err.Error()))
		return &types.ReviewInfo{}, nil
	}

	if res == nil || res.Id == nil || *res.Id == 0 {
		return &types.ReviewInfo{}, nil
	}

	var viewCount *uint32
	var commentCount *uint32
	var forwardCount *uint32
	var mediaUrl *string
	if len(res.Meta) > 0 {
		for _, v := range res.Meta {
			if v.Key == nil || v.Value == nil {
				continue
			}

			val := *v.Value
			switch *v.Key {
			case "viewCount":
				if i, err := strconv.ParseInt(val, 10, 32); err == nil {
					viewCount = pointy.GetPointer(uint32(i))
				}
			case "commentCount":
				if i, err := strconv.ParseInt(val, 10, 32); err == nil {
					commentCount = pointy.GetPointer(uint32(i))
				}
			case "forwardCount":
				if i, err := strconv.ParseInt(val, 10, 32); err == nil {
					forwardCount = pointy.GetPointer(uint32(i))
				}
			case "mediaUrl":
				mediaUrl = pointy.GetPointer(val)
			}
		}
	}

	var media []*types.TmpMediaInfo
	if len(res.Media) > 0 {
		for _, v := range res.Media {
			var url string
			if v.Url != nil && len(*v.Url) > 0 {
				url = *v.Url
			}
			if len(url) == 0 && v.Uri != nil && len(*v.Uri) > 0 {
				url = *v.Uri
			}

			media = append(media, &types.TmpMediaInfo{
				Uid:       v.Uid,
				Id:        v.Id,
				Thumbnail: v.Thumbnail,
				Order:     v.Order,
				Url:       pointy.GetPointer(url),
				AltText:   v.AltText,
			})
		}
	}

	var tags []*types.TermInfo
	if len(res.Tags) > 0 {
		for _, v := range res.Tags {
			tags = append(tags, &types.TermInfo{
				Id:   v.Id,
				Name: v.Name,
				Slug: v.Slug,
			})
		}
	}

	var cards []*types.CardInfo
	if len(res.Cards) > 0 {
		for _, v := range res.Cards {
			cards = append(cards, &types.CardInfo{
				Uid:      v.Uid,
				Id:       v.Id,
				Type:     v.Type,
				LinkUrl:  v.LinkUrl,
				Title:    v.Title,
				PicUrl:   v.PicUrl,
				Subtitle: v.Subtitle,
				Label:    v.Label,
				Price:    v.Price,
			})
		}
	}

	*headers = []*types.Header{
		{
			Key:   "x-class",
			Value: "com.djx.appview.MallForumPostPage",
		},
	}

	return &types.ReviewInfo{
		Id:              res.Id,
		Title:           res.PostTitle,
		ContentHtml:     res.PostContent,
		Excerpt:         res.PostExcerpt,
		ParentId:        res.ParentId,
		AuthorId:        res.AuthorId,
		CommentStatus:   res.CommentStatus,
		CreatedAt:       res.CreatedAt,
		UpdatedAt:       res.UpdatedAt,
		AuthorAvatar:    res.AuthorAvatar,
		AuthorNickname:  res.AuthorNickname,
		AuthorSignature: res.AuthorSignature,
		AuthorRankId:    res.AuthorRankId,
		AuthorRoleId:    res.AuthorRoleId,
		ImageUrl:        mediaUrl,
		PhotoCount:      res.PhotoCount,
		ViewCount:       viewCount,
		CommentCount:    commentCount,
		ForwardCount:    forwardCount,
		Media:           media,
		Cards:           cards,
		Tags:            tags,
	}, nil
}

func (l *GetReviewByIdLogic) getReviewById(
	reviewId *uint64,
	userId uint64,
	authorId uint64,
) (*types.ReviewInfo, error) {
	preload := "forumPost:Id,Title,ParentId,ContentHtml"
	eagerLoad := "forumPost:forumMedia"
	var filters []string
	filters = append(filters, "ForumId,equalTo:"+strconv.FormatInt(l.svcCtx.Config.Query.PostForumId, 10))
	filters = append(filters, "AuthorId,equalTo:"+strconv.FormatUint(authorId, 10))

	if userId == authorId {
		preload += ",Status"
		filters = append(filters, "Status,notEqualTo:"+strconv.FormatInt(int64(globalkey.StatusDeleted), 10))
	} else {
		filters = append(filters, "Status,equalTo:"+strconv.FormatInt(int64(globalkey.StatusApproved), 10))
	}
	preload += ";forumMedia:Id,Uid,Uri,Url,Order,Thumbnail"

	res, err := l.svcCtx.ForumRpc.GetReviewById(l.ctx, &forumclient.BaseIdReq{
		Id:         reviewId,
		Preload:    pointy.GetPointer(preload),
		EagerLoad:  pointy.GetPointer(eagerLoad),
		Filter:     pointy.GetPointer(strings.Join(filters, ";")),
		VisitorId:  pointy.GetPointer(userId),
		PlatformId: pointy.GetPointer(globalkey.ThirdPartyPlatformWechatMini),
	})
	if err != nil {
		logx.Errorw("getReviewById err", logx.Field("detail", err.Error()))
		return &types.ReviewInfo{}, nil
	}

	if res == nil || res.Id == nil || *res.Id == 0 {
		return &types.ReviewInfo{}, nil
	}

	var media []*types.TmpMediaInfo
	if len(res.Media) > 0 {
		for _, v := range res.Media {
			var url string
			if v.Url != nil && len(*v.Url) > 0 {
				url = *v.Url
			}
			if len(url) == 0 && v.Uri != nil && len(*v.Uri) > 0 {
				url = *v.Uri
			}

			media = append(media, &types.TmpMediaInfo{
				Uid:       v.Uid,
				Id:        v.Id,
				Thumbnail: v.Thumbnail,
				Order:     v.Order,
				Url:       pointy.GetPointer(url),
				AltText:   v.AltText,
			})
		}
	}

	var parent *types.KbEntryInfo
	if res.ParentId != nil && *res.ParentId > 0 {
		parent, err = l.getParentById(res.ParentId)
		if err != nil {
			return nil, err
		}
	}

	return &types.ReviewInfo{
		Id:              res.Id,
		Title:           res.PostTitle,
		ContentHtml:     res.PostContent,
		ParentId:        res.ParentId,
		AuthorId:        res.AuthorId,
		CommentStatus:   res.CommentStatus,
		CreatedAt:       res.CreatedAt,
		AuthorAvatar:    res.AuthorAvatar,
		AuthorNickname:  res.AuthorNickname,
		AuthorSignature: res.AuthorSignature,
		AuthorRankId:    res.AuthorRankId,
		AuthorRoleId:    res.AuthorRoleId,
		Parent:          parent,
		Media:           media,
	}, nil
}

func (l *GetReviewByIdLogic) getParentById(pid *uint64) (*types.KbEntryInfo, error) {
	preload := "blogBook:Id,Title,Slug;blogBookMeta:mediaUrl;blogMedia:Uri,Url"
	eagerLoad := "blogBook:blogBookMeta,blogMedia"
	var filters []string
	filters = append(filters, "Status,equalTo:"+strconv.FormatInt(int64(globalkey.PostStatusPublish), 10))

	res, err := l.svcCtx.BlogRpc.GetKBPostById(l.ctx, &blogclient.BaseIdReq{
		Id:        pid,
		Preload:   pointy.GetPointer(preload),
		EagerLoad: pointy.GetPointer(eagerLoad),
		Filter:    pointy.GetPointer(strings.Join(filters, ";")),
	})
	if err != nil {
		logx.Infow("GetReviewById getParentById BlogRpc.GetKBPostById err", logx.Field("detail", err.Error()))
		return nil, err
	}

	if res == nil || res.Id == nil || *res.Id == 0 {
		return &types.KbEntryInfo{}, nil
	}

	var mediaUrl *string
	if len(res.Meta) > 0 {
		for _, v := range res.Meta {
			if v.Key == nil || v.Value == nil {
				continue
			}

			val := *v.Value
			switch *v.Key {
			case "mediaUrl":
				mediaUrl = pointy.GetPointer(val)
			}
		}
	}

	// var media []*types.TmpMediaInfo
	if mediaUrl == nil && len(res.Media) > 0 {
		for _, v := range res.Media {
			var url string
			if v.Url != nil && len(*v.Url) > 0 {
				url = *v.Url
			}
			if len(url) == 0 && v.Uri != nil && len(*v.Uri) > 0 {
				url = *v.Uri
			}
			if len(url) > 0 {
				mediaUrl = pointy.GetPointer(url)
			}
		}
	}

	return &types.KbEntryInfo{
		Id:       res.Id,
		Title:    res.Title,
		Slug:     res.Slug,
		ImageUrl: mediaUrl,
	}, nil
}
